
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html class="pageview">


<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<base target="_top">
<style type="text/css">
  

/* default css */

table {
  font-size: 1em;
  line-height: inherit;
  border-collapse: collapse;
}


tr {
  
  text-align: left;
  
}


div, address, ol, ul, li, option, select {
  margin-top: 0px;
  margin-bottom: 0px;
}

p {
  margin: 0px;
}


pre {
  font-family: Courier New;
  white-space: pre-wrap;
  margin:0;
}

body {
  margin: 6px;
  padding: 0px;
  font-family: Verdana, sans-serif;
  font-size: 10pt;
  background-color: #ffffff;
}


img {
  -moz-force-broken-image-icon: 1;
}

@media screen {
  html.pageview {
    background-color: #f3f3f3 !important;
  }

  

  body {
    min-height: 1100px;
    
    counter-reset: __goog_page__;
  }
  * html body {
    height: 1100px;
  }
  .pageview body {
    border-top: 1px solid #ccc;
    border-left: 1px solid #ccc;
    border-right: 2px solid #bbb;
    border-bottom: 2px solid #bbb;
    width: 648px !important;
    margin: 15px auto 25px;
    padding: 40px 50px;
  }
  /* IE6 */
  * html {
    overflow-y: scroll;
  }
  * html.pageview body {
    overflow-x: auto;
  }
  /* Prevent repaint errors when scrolling in Safari. This "Star-7" css hack
     targets Safari 3.1, but not WebKit nightlies and presumably Safari 4.
     That's OK because this bug is fixed in WebKit nightlies/Safari 4 :-). */
  html*#wys_frame::before {
    content: '\A0';
    position: fixed;
    overflow: hidden;
    width: 0;
    height: 0;
    top: 0;
    left: 0;
  }
  
  

  
    .writely-callout-data {
      display: none;
      *display: inline-block;
      *width: 0;
      *height: 0;
      *overflow: hidden;
    }
    .writely-footnote-marker {
      background-image: url('MISSING');
      background-color: transparent;
      background-repeat: no-repeat;
      width: 7px;
      overflow: hidden;
      height: 16px;
      vertical-align: top;

      
      -moz-user-select: none;
    }
    .editor .writely-footnote-marker {
      cursor: move;
    }
    .writely-footnote-marker-highlight {
      background-position: -15px 0;
      -moz-user-select: text;
    }
    .writely-footnote-hide-selection ::-moz-selection, .writely-footnote-hide-selection::-moz-selection {
      background: transparent;
    }
    .writely-footnote-hide-selection ::selection, .writely-footnote-hide-selection::selection {
      background: transparent;
    }
    .writely-footnote-hide-selection {
      cursor: move;
    }

    
    .editor .writely-comment-yellow {
      background-color: #FF9;
      background-position: -240px 0;
    }
    .editor .writely-comment-yellow-hover {
      background-color: #FF0;
      background-position: -224px 0;
    }
    .editor .writely-comment-blue {
      background-color: #C0D3FF;
      background-position: -16px 0;
    }
    .editor .writely-comment-blue-hover {
      background-color: #6292FE;
      background-position: 0 0;
    }
    .editor .writely-comment-orange {
      background-color: #FFDEAD;
      background-position: -80px 0;
    }
    .editor .writely-comment-orange-hover {
      background-color: #F90;
      background-position: -64px 0;
    }
    .editor .writely-comment-green {
      background-color: #99FBB3;
      background-position: -48px 0;
    }
    .editor .writely-comment-green-hover {
      background-color: #00F442;
      background-position: -32px 0;
    }
    .editor .writely-comment-cyan {
      background-color: #CFF;
      background-position: -208px 0;
    }
    .editor .writely-comment-cyan-hover {
      background-color: #0FF;
      background-position: -192px 0;
    }
    .editor .writely-comment-purple {
      background-color: #EBCCFF;
      background-position: -144px 0;
    }
    .editor .writely-comment-purple-hover {
      background-color: #90F;
      background-position: -128px 0;
    }
    .editor .writely-comment-magenta {
      background-color: #FCF;
      background-position: -112px 0;
    }
    .editor .writely-comment-magenta-hover {
      background-color: #F0F;
      background-position: -96px 0;
    }
    .editor .writely-comment-red {
      background-color: #FFCACA;
      background-position: -176px 0;
    }
    .editor .writely-comment-red-hover {
      background-color: #FF7A7A;
      background-position: -160px 0;
    }

    .editor .writely-comment-marker {
      background-image: url('MISSING');
      background-color: transparent;
      padding-right: 11px;
      background-repeat: no-repeat;
      width: 16px;
      height: 16px;
      -moz-user-select: none;
    }

    .editor .writely-comment-hidden {
      padding: 0;
      background: none;
    }
    .editor .writely-comment-marker-hidden {
      background: none;
      padding: 0;
      width: 0;
    }
    .editor .writely-comment-none {
      opacity: .2;
      filter:progid:DXImageTransform.Microsoft.Alpha(opacity=20);
      -moz-opacity: .2;
    }
    .editor .writely-comment-none-hover {
      opacity: .2;
      filter:progid:DXImageTransform.Microsoft.Alpha(opacity=20);
      -moz-opacity: .2;
    }
  


  
  .br_fix br:not(:-moz-last-node):not(:-moz-first-node) {
    
    position:relative;
    
    left: -1ex
    
  }
  
  .br_fix br+br {
    position: static !important
  }
}

h6 { font-size: 8pt }
h5 { font-size: 8pt }
h4 { font-size: 10pt }
h3 { font-size: 12pt }
h2 { font-size: 14pt }
h1 { font-size: 18pt }

blockquote {padding: 10px; border: 1px #DDD dashed }

a img {border: 0}

.pb {
  border-width: 0;
  page-break-after: always;
  /* We don't want this to be resizeable, so enforce a width and height
     using !important */
  height: 1px !important;
  width: 100% !important;
}

.editor .pb {
  border-top: 1px dashed #C0C0C0;
  border-bottom: 1px dashed #C0C0C0;
}

div.google_header, div.google_footer {
  position: relative;
  margin-top: 1em;
  margin-bottom: 1em;
}


/* Table of contents */
.editor div.writely-toc {
  background-color: #f3f3f3;
  border: 1px solid #ccc;
}
.writely-toc > ol {
  padding-left: 3em;
  font-weight: bold;
}
ol.writely-toc-subheading {
  padding-left: 1em;
  font-weight: normal;
}
/* IE6 only */
* html writely-toc ol {
  list-style-position: inside;
}
.writely-toc-none {
  list-style-type: none;
}
.writely-toc-decimal {
  list-style-type: decimal;
}
.writely-toc-upper-alpha {
  list-style-type: upper-alpha;
}
.writely-toc-lower-alpha {
  list-style-type: lower-alpha;
}
.writely-toc-upper-roman {
  list-style-type: upper-roman;
}
.writely-toc-lower-roman {
  list-style-type: lower-roman;
}
.writely-toc-disc {
  list-style-type: disc;
}

/* Ordered lists converted to numbered lists can preserve ordered types, and
   vice versa. This is confusing, so disallow it */
ul[type="i"], ul[type="I"], ul[type="1"], ul[type="a"], ul[type="A"] {
  list-style-type: disc;
}

ol[type="disc"], ol[type="circle"], ol[type="square"] {
  list-style-type: decimal;
}

/* end default css */


  /* default print css */
  
  @media print {
    body {
      padding: 0;
      margin: 0;
    }

    div.google_header, div.google_footer {
      display: block;
      min-height: 0;
      border: none;
    }

    div.google_header {
      flow: static(header);
    }

    /* used to insert page numbers */
    div.google_header::before, div.google_footer::before {
      position: absolute;
      top: 0;
    }

    div.google_footer {
      flow: static(footer);
    }

    /* always consider this element at the start of the doc */
    div#google_footer {
      flow: static(footer, start);
    }

    span.google_pagenumber {
      content: counter(page);
    }

    span.google_pagecount {
      content: counter(pages);
    }


    callout.google_footnote {
      
      display: prince-footnote;
      footnote-style-position: inside;
      /* These styles keep the footnote from taking on the style of the text
         surrounding the footnote marker. They can be overridden in the
         document CSS. */
      color: #000;
      font-family: Verdana;
      font-size: 10.0pt;
      font-weight: normal;
    }

    /* Table of contents */
    #WritelyTableOfContents a::after {
      content: leader('.') target-counter(attr(href), page);
    }

    #WritelyTableOfContents a {
      text-decoration: none;
      color: black;
    }
  }

  @page {
    @top {
      content: flow(header);
    }
    @bottom {
      content: flow(footer);
    }
    @footnotes {
      border-top: solid black thin;
      padding-top: 8pt;
    }
  }
  /* end default print css */


/* custom css */


/* end custom css */

/* ui edited css */

body {
  font-family: Verdana;
  
  font-size: 10.0pt;
  line-height: normal;
  background-color: #ffffff;
}
/* end ui edited css */


/* editor CSS */
.editor a:visited {color: #551A8B}
.editor table.zeroBorder {border: 1px dotted gray}
.editor table.zeroBorder td {border: 1px dotted gray}
.editor table.zeroBorder th {border: 1px dotted gray}


.editor div.google_header, .editor div.google_footer {
  border: 2px #DDDDDD dashed;
  position: static;
  width: 100%;
  min-height: 2em;
}

.editor .misspell {background-color: yellow}

.editor .writely-comment {
  font-size: 9pt;
  line-height: 1.4;
  padding: 1px;
  border: 1px dashed #C0C0C0
}


/* end editor CSS */

</style>

  
  <title>Magnetic Flocks: Design Document</title>

</head>

<body
    
    
    revision="df4pptd2_29444qcccs:185">

    
    
    
<h1>
  Magnetic Flocks: Flocks Design Document
</h1>
<i>by Jian Wei Gan (Wei) and Thomas Marmaduke (Tom)<br>
</i>March 29, 2009<br>
<h2>
  Introduction
</h2>
Flocks is a Java program that simulates leaderless-flock group behavior. It provides a Graphical User Interface in which you can view the flock's movement as well as tweak attributes of the flock.<br>
Our goal for Flocks is to write a <b>reusable, general GUI/animation engine</b> to view and manipulate groups of items (flocks, bouncing balls etc...) while they are moving <b>and </b>to implement a <b>specific group the exhibits flock behavior</b> that can work with this GUI.<br>
Our specific design goal is for Flocks to be open to displaying different types of groups (i.e. not just flocks of birds) but closed to modification of the GUI and the interface between the GUI and the group(s) being displayed.<br>
<h2>
  Overview
</h2>
Flocks is split into the <b>reusable portion</b>, which constitutes the GUI, classes in the engine package that provide the 'glue' between the GUI and the objects to be animated, as well as abstract classes that groups/sprites to be shown in the GUI must extend, and the <b>specific portion </b>which constitutes of the Flock, FlockFactory and FlockMember classes.<br>
<br>
We split the project into packages: gui, generics and engine are packages that are the <b>framework</b> of the program, while flock is a specific example of an implementation of a group to animate using this framework. reflection is a utility package that we use to dynamically create groups based on their names. resources is a data package which contains properties files with strings to be displayed in the gui or other string constants used in the program.<br>
<br>
We have a Main class and an Applet class so that the GUI can be viewed as a Java Applet as well as a Java Application.<br>
<br>
The GUI components are all instantiated in the Applet class, currently including the sliders, the 'Add New Flock' button and the Canvas.<br>
The Canvas is the "screen" to watch the movement/behavior of the group(s). Current implementation only allows for 1 group at a time.<br>
Canvas holds a list of Group objects, which will be populated with Groups that are created to be shown on the "screen."<br>
<br>
The animation works like this: For every frame set in a Timer in the Applet class, the Canvas is updated, which in turn calls the Groups currently on the Canvas to update themselves.<br>
<div>
  <br>
  <h2>
    User Interface Design
  </h2>
  The user interface consists of a main container which is the applet, with a minimal file menu that has a quit item. The top of the main panel is the button panel, where there are standard clear viewer and remove groups buttons, as well as an 'Add New Flock' button. If you were to support new groups being animated, the buttons to create them would reside in this panel. The main part of this panel is the canvas or display. This area has a white background and is used to display the animations and sprites. The right side of the window is the settings panel, which consists of two parts: the group chooser at the top and the scrollable sliders panel at the bottom.<br>
  <br>
  The user interacts with the program by clicking 'Add New Flock' since the canvas is empty when the program starts. After this, a flock appears on the canvas and the settings panel dynamically updates itself to show the newly added flock in the group chooser as well as it's attributes in the sliders panel. The user can manipulate the sliders to adjust attributes of the flock shown in the chooser.<br>
  <br>
  The use can then add more groups by clicking the 'Add New Flock' button again and the settings panel will dynamically update to display settings of the latest flock being added. The user can also choose between different flocks to manipulate by using the group chooser's drop down menu. The user can also remove any flock on the canvas by selecting the flock to remove in the group chooser and then clicking the remove group button.<br>
  <br>
  Here's a screenshot of the GUI, showing 2 flocks on the display. Also, the user has clicked on the group chooser to show the drop down menu.<br>
  <div id=pvh5 style=TEXT-ALIGN:left>
    <img src=Magnetic_Flocks_Design__images/df4pptd2_30d9x4q6hm_b.png style="WIDTH:648px; HEIGHT:429.693px">
  </div>
  <br>
  The goal of the UI was to have the settings panel dynamically update itself to whatever kind of group is chosen in the group chooser, i.e. the settings can display different types of settings based on attributes of the group being shown.<br>
  <h2>
    Design Details
  </h2>
  We split the project into different packages based on how the classes functioned as part of the program.<br>
  <ul>
    <li>
      The <b>default package</b> has the Applet (top level container for GUI) and Main (allows you to run this as a Java application using the Applet code) classes.
    </li>
    <li>
      The <b>gui</b> package contains all the GUI elements of the program:
    </li>
  </ul>
  <ul>
    <ul>
      <li>
        Canvas: the display for animations/sprites
      </li>
      <li>
        ButtonPanel: a panel with buttons for adding and removing groups from the display<br>
      </li>
      <li>
        SettingsPanel: a panel that allows you to select a group and shows sliders which let you manipulate the chosen group's settings
      </li>
      <li>
        RangeSlider: a basic slider that lets you create it with a name and a max and min value.
      </li>
      <li>
        AttributeSlider: a RangeSlider that is associated with an attribute of a group, it lets you manipulate the associated attribute<br>
      </li>
      <li>
        ResourceStrings: a utility class with static methods that allow other classes to read strings from a properties file
      </li>
    </ul>
    <li>
      The <b>engine</b> package contains classes that serve back-end functions of the framework by acting as the glue between the GUI and the objects to be animated
    </li>
    <ul>
      <li>
        Attribute: gives a template for group attributes/properties, allows for a standard template to access properties when creating sliders in the GUI
      </li>
      <li>
        Factory: a class that reflectively creates groups based on a string of their class' name, associated with the FactoryButton inner class
      </li>
    </ul>
    <li>
      The <b>generics</b> package contains abstract classes that serve as a base for implementing new types of sprites, animations or groups
    </li>
    <ul>
      <li>
        AbstractSprite: A generic sprite to be displayed<br>
      </li>
      <li>
        AbsractMover: A generic sprite that has functionality to move when animated
      </li>
      <li>
        AbstractGroupMember: A implementation of AbstractMover that belongs to a group
      </li>
      <li>
        AbstractGroup: A generic collection of AbstractGroupMembers that holds changeable attributes<br>
      </li>
    </ul>
    <li>
      The <b>flock</b> package is an example of how to implement the abstract classes in generics to show on the display.
    </li>
    <ul>
      <li>
        Flock: A specific implementation of an AbstractGroup that exhibits leaderless flock-like behavior based on algorithms of separation, cohesion and alignment
      </li>
      <li>
        FlockMember: A specific implementation of AbstractGroupMember that behaves as part of a leaderless flock
      </li>
    </ul>
    <li>
      The <b>reflection </b>package is a utility package that allows for us to dynamically create classes and invoke methods (Thanks to Prof Duvall for supplying this)<br>
    </li>
  </ul>
  <br>
  <h4>
    Class Details
  </h4>
  <br>
</div>
<div>
  <u>Main</u><br>
  This initializes the program's GUI with a default size of 800 x 600 pixels. It does this by initializing the applet and packing it into a JFrame before displaying it to the user. This class is to initialize the program when it is to be run as a java application (as opposed to a web applet.)<br>
  <br>
  <u>Applet<br>
  </u>This class is the top level GUI container in this program. When initialized, it sets up the menu bar, button panel, settings panel and canvas, as well as the timer which updates the canvas to display animations (by calling update() on canvas.) The frame speed can be changed by altering the DEFAULT_DELAY constant. This applet allows for the program to be displayed as a Java applet in a browser.<br>
  <br>
  <span style=BACKGROUND-COLOR:#ffff00>Most importantly, this class hols a static final array of classes in SUPPORTED_GROUPS which has the classes of Groups currently supported by the program.<br>
  <span style=BACKGROUND-COLOR:#ffffff>If you create another type of group to be animated in the canvas, all you need to do after you create classes that extend AbstractGroup and AbstractGroupMember is to write in the name of the group followed by '.class' into this list. i.e. to add BouncingBalls you would add 'BouncingBalls.class' into this array and the program will generate rest of the GUI components for you, i.e a FactoryButton 'Add New BoundingBalls' and sliders when you choose the group.<br style=BACKGROUND-COLOR:#ffff00>
  </span></span>
  <h4>
    gui
  </h4>
  <u>Canvas</u><br>
  This class animates groups of movers against a white background. The most important thing to note is canvas holds the list of groups currently being shown on it. So if other classes need to access the list of groups, the only way is to call getGroups() on the canvas.<br>
  paintComponent() is implemented to draw a background then the groups on the background and is called by Java runtime when the window is resized or at start up.<br>
  update() is called by the applet at certain time intervals to show the animation. i.e. update is called in every "frame" of the animation.<br>
  <br>
  <u>ButtonPanel<br>
  </u>This class creates standard buttons 'Clear Viewer' and 'Remove Group' as well as FactoryButtons for each group that's supported (look at SUPPORTED_GROUPS array in Applet.)<br>
  'Clear Viewer' removes all group from the group chooser and the canvas, while 'Remove Group' removes the group that's currently selected in the viewer.<br>
  <br>
  This class also contains the FactoryButton inner class which is used to create buttons 'Add New (groupname)' for supported groups. It uses the Factory it is associated with to create the group in the canvas. I implemented ActionListener so that I could write the actionPerformed() method in the same class as the JButton (i.e. FactoryButton.)<br>
  <br>
  <u>SettingsPanel<br>
  </u>This class consists of the GroupChooser and a scroll pane which holds the sliders panel. It is the only class the holds the group chooser so to access the group chooser, other GUI components have to go through the settings panel. The button panel's factory button adds a group to the chooser by calling addChoosable(group) on the settings panel. Also, updateSliders(group) is called to update the entire sliders panel with respect to the group passed in.<br>
  <br>
  This class contains the inner class GroupChooser which implements a combo box (drop down menu) that lets you choose which group's attributes/settings you want to see and manipulate in the sliders panel.<br>
  <br>
  <u>AttributeSlider<br>
  </u>This is an implementation of RangeSlider that links the slider to the instance of Attribute passed in when the attribute slider is constructed.<br>
  <u><br>
  ResourceStrings<br>
  </u>This is a utility class that initializes a ResourceBundle from a properties file statically and allows all other classes to access this ResourceBundle. The language setting for the program is in this class' LANGUAGE static final string. It contains a static method getString(key) so that classes in this program can easily access files in this resourcebundle while keeping the resource bundle a private variable and shortening the syntax to ResourceStrings.getString(key) instead of ResourceStrings.getResources.getString(key) if I were to set a get for the myResources instance variable.<br>
  <h4>
    engine
  </h4>
  <u>Factory<br>
  </u>This class is used to reflectively create groups of type passed in through the constructor.<br>
  It leverages the reflection package to eliminate the need for a 'FlockFactory' or other factories specific to their group type in the createGroup(canvas) method. Instead, a developer using this framework would only need to add the new type of group to SUPPORTED_GROUPS in Applet.java and a factory will be instantiated for each type of group when the FactoryButtons are created in the GUI. It also keeps track of the number created so that it can label the groups in the chooser e.g. 'Flock 2' for the second flock that was created. Current implementation doesn't reset this number after groups are removed from the canvas.<br>
  It also supports getNewestGroup() so that the group chooser can access the newest group that has been added and display it's settings right after it is created by the factory.<br>
  <u><br>
  Attributes<br>
  </u>This class acts as a wrapper for the an attribute's name and it's minimum, maximum and current values. It allows the attribute sliders to access the settings of a group easily.<br>
  <h4>
    generics
  </h4>
  <u>AbstractGroup<br>
  </u>This class is meant to subclassed by things that implement a collection of sprites e.g. a Flock of boids. It supports basic group attributes such as a list of attributes, a list of its members and an index, which is the equal to myNumCreated in the Factory at the point this group was created. (The index is 1-based.)<br>
  <br>
  Contains an abstract update(canvas) method that must be implemented to change the group for each frame. This update(canvas) is called by the canvas on all groups in it.<br>
  <br>
  It supports gets for it's center coordinates, it's index, as well as it's attributes list and the list of members it holds. The specific reasons for having these get methods is in the javadoc comments in the code.<br>
  <br>
  There is an abstract toString() method that needs to be implemented to show "(group name) (index)". This cannot be done in this class because it would always be named "Group (index)".<br>
  <br>
  The parameter map is required because we cannot randomly access the attributes list by attributes. So the parameter map maps names of the attributes to the current values and is updated in updateParameter(), where the parameter map is updated with current values from the attributes list (which changes when sliders are moved.) We considered having some kind of class that would be a data stucture to allow us to randomly access attributes, or having an attribute name to attribute map, but have yet to decide on whether these implementations are better than the one now.<br>
  <u><br>
  AbstractSprite<br>
  </u>This class implements a generic sprite that is has a paint(pen) method but does not have an update() method, i.e. it cannot be moved around, but has standard fields such as center, size, color and type. It also has a getDistance(point) method which finds the distance between a the sprite and a given coordinate.<br>
  <u><br>
  AbstractMover<br>
  </u>This class is a subclass of AbstractSprite that has a velocity and trail fields. It also has an update(canvas) method that is called to allow the mover to be animated on the canvas.<br>
  <br>
  It also has a wrap method which alters the center (and hence position) of the sprite once it goes off one side of the canvas such that it reappears at the opposite side (like a flattened torus.)<br>
  <br>
  We left the trail code in here even though we removed the implementation because we thought it might be useful in future cases for debugging.<br>
  <br>
  <u>AbstractGroupMember<br>
  </u>This class is a subclass of AbstractMover but has a field myGroup, which is the group the groupmember belongs to.<br>
  <h4>
    flock
  </h4>
  <u>Flock<br>
  </u>This class is an implementation of a group of boids that flock together, simulating leaderless flock behavior.<br>
  <br>
  We statically fill in the parameter data map that is used to initialize the flock because it need only be computed once when the Flock is initialized.<br>
  <br>
  This group supports updateFlockSize() which makes sure the number of FlockMembers equals the NUMBER parameter of the flock. It also supports a public addFlockMember() method that's can be implemented indepently of updateFlockSize() in future if desired.<br>
  <br>
  <u>FlockMember<br>
  </u>This class contains all the algorithms for the flock member to exhibit leaderless flock behavior, based on principles of cohesion, alignment and acceleration.<br>
  <br>
  Ultimately, the updateVelocity(..) method updates the flock member's velocity after these calculations have been done and this is called in the update method, which is called in the Flock's updateMember(member) method.<br>
  <br>
  It also implements a paint(pen) method that describes how to draw the flock member, which is currently a resizable rectangle.<br>
  <h2>
    Design Considerations
  </h2>
  The main design consideration was making sure the GUI/Animation Engine is as general as possible. To do this, we had to create a framework for creating a new type of group to be animated, which is the reason for the AbstractGroup and AbstractGroupMember methods.<br>
  <br>
  We concentrated on how to make it easy to add a new type of group to be animated. Writing the group and group member might still take some work and referring to the programmer manual but <span style=BACKGROUND-COLOR:#fce5cd>it is very simple to add the group to the canvas as adding a "(groupname).class" to the SUPPORTED_GROUPS array in Applet.java and the GUI components to support it are automatically generated.</span><br>
  <br>
  <h2>
    Remaining Issues
  </h2>
  Our framework only supports animation of groups now, so to add an individual sprite to be animated, a developer would have to add a group with one group member. Ideally, our framework should be able to support individual sprites/movers that are not part of a group. So the canvas would not hold a list of groups but rather a list of drawables. We could then have a Drawable interface that would require a paint() method and maybe an Animatable that would also require an update() method. So the canvas would be able to handle not only groups but individual sprites as well without having to go create an arbitrary 1 sprite group.<br>
  <br>
  We would also refactor the inheritance hierarchy for the AbstractSprite, Mover etc. because currently it's not tested very well on whether it's useful because the animation engine only supports drawing of groups now.<br>
  <br>
  We would then improve the GUI to support features like Settings or Attributes of items that are not only numerical, but maybe be able to choose between a bunch of colors for a group for example. The GUI could also have options such as frame by frame animation where the user steps through the frames by clicking a button that would be useful for debugging.<br>
  <h2>
    Team Responsibilities
  </h2>
  Tom: Flocking algorithm, Flock behavior, GUI/Group interface, Programmer Manual<br>
  Wei: GUI components, GUI/Group interface, Design Document<br>
  <br>
  Towards the end we looked over the whole project together and figured out which parts we had to change to make more extensible, e.g. abstract classes<br>
</div>
<br></body>
</html>